﻿Public Class PrintGraphItem
    Inherits PrintItem

	Public Overrides Sub Draw(ByVal G As System.Drawing.Graphics, Path As Drawing2D.GraphicsPath)
		G.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
		Select Case Attribute("type")
			Case "3dbar"
				Dim Depth = (y2 - y1) / 10
				Dim TickSize = (x2 - x1) / 200
				Dim P1 As New PointF(x1 + TickSize * 10, y1 + Depth)
				Dim P2 As New PointF(x1 + TickSize * 10, y2 - TickSize * 10)
				Dim P3 As New PointF(x2 - +TickSize * 10 - Depth, y2 - +TickSize * 10)
				Dim y, x, Interval
				Dim Font As Font
				DrawPlane(G, P1, P2, Depth, True)
				DrawPlane(G, P2, P3, Depth, True)
				Font = New Font(ReportFontRegular, If((P2.Y - P1.Y) < 40, 1, (P2.Y - P1.Y) / 40))
				If Attribute("maxval") <= Attribute("minval") Then Attribute("maxval") = Attribute("maxval") + 1
				For i As Double = Attribute("minval") To Attribute("maxval") Step Attribute("interval")
					y = P2.Y - ((i - Attribute("minval")) / (Attribute("maxval") - Attribute("minval"))) * (P2.Y - P1.Y)
					G.DrawLine(LinePen, P1.X, CInt(y), P1.X - CInt(TickSize), CInt(y))
					Dim TextSize As SizeF = G.MeasureString(Trim(i), Font)
					DrawText(G, Trim(i), Font, Color.Black, New Rectangle(CInt(P1.X - TextSize.Width - TickSize * 2), CInt(y - TextSize.Height / 2), TextSize.Width, TextSize.Height))
				Next
				G.TranslateTransform(P2.X, P2.Y)
				G.RotateTransform(-90)
				Dim Size As SizeF = G.MeasureString(Attribute("axistitle"), Font)
				DrawText(G, Attribute("axistitle"), Font, Color.Black, New Rectangle((P2.Y - P1.Y - Size.Width) / 2, -Size.Height - G.MeasureString("123456", Font).Width, 100, 100))
				G.RotateTransform(90)
				G.TranslateTransform(-P2.X, -P2.Y)
				Dim Titles = Split(Attribute("titles"), ";")
				Interval = 1 / (UBound(Titles) + 1) * (P3.X - P2.X)
				For i As Double = 0 To UBound(Titles) + 1
					x = P2.X + i * Interval
					G.DrawLine(LinePen, CInt(x), P2.Y, CInt(x), P2.Y + CInt(TickSize))
				Next
				Dim Values = Split(Attribute("values"), ";")
				Font = New Font(ReportFontRegular, If((P2.Y - P1.Y) < 30, 1, (P2.Y - P1.Y) / 30))
				For i As Double = 0 To UBound(Values)
					Dim xx1 = P2.X + i * Interval
					Dim xx2 = P2.X + (i + 1) * Interval
					Dim yy2 = P2.Y
					Dim yy1 = P2.Y - (Val(Values(i)) - Attribute("minval")) / (Attribute("maxval") - Attribute("minval")) * (P2.Y - P1.Y)
					Dim TextSize As SizeF = G.MeasureString(Titles(i), Font)
					DrawText(G, Titles(i), Font, Color.Black, New Rectangle(xx1 + (Interval - TextSize.Width) / 2, yy2 + TickSize * 2, TextSize.Width, TextSize.Height))
					TextSize = G.MeasureString(Values(i), Font)
					DrawText(G, Values(i), Font, Color.Black, New Rectangle(xx1 + (Interval - TextSize.Width) / 2 + Depth / 2, yy1 - TextSize.Height * 2 - Depth / 2, TextSize.Width, TextSize.Height))
					xx1 += Interval / 4
					xx2 -= Interval / 4
					xx1 += Depth / 4
					xx2 += Depth / 4
					yy1 -= Depth / 4
					yy2 -= Depth / 4
					Dim Box(3) As PointF
					Box(0) = New Point(xx1, yy1)
					Box(1) = New Point(xx1, yy2)
					Box(2) = New Point(xx2, yy2)
					Box(3) = New Point(xx2, yy1)
					DrawPlane(G, Box(0), Box(3), Depth / 2)
					DrawPlane(G, Box(3), Box(2), Depth / 2)
					G.FillPolygon(Brushes.White, Box)
					G.DrawPolygon(LinePen, Box)
				Next
			Case "3dpie"
				Dim Total As Double = 0
				Dim Values = Split(Attribute("values"), ";")
				Dim Titles = Split(Attribute("titles"), ";")
				Dim i As Integer
				Dim Pies(UBound(Values)) As Pie
				Dim Count As Integer = UBound(Values) + 1
				Dim Digits As Integer = 0
				For i = 0 To Count - 1
					Pies(i) = New Pie
					Pies(i).Title = Titles(i)
					Pies(i).Value = Val(Values(i))
					Total += Pies(i).Value
				Next
				If Total = 0 Then Exit Sub
				For i = 0 To Count - 1
					Pies(i).PrevPie = Pies((i + Count - 1) Mod Count)
					Pies(i).NextPie = Pies((i + 1) Mod Count)
				Next
				For i = 0 To Count - 1
					Pies(i).PercentValue = Pies(i).Value / Total * 100
					Pies(i).Angle = Pies(i).Value / Total * 360
				Next
				Digits = 2
				For i = 0 To Count - 1
					Pies(i).Percent = "%" & Format(Pies(i).PercentValue, "###0" & If(Digits = 0, "", "." & Strings.StrDup(Digits, "0")))
					Pies(i).Angle = Pies(i).Value / Total * 360
				Next
				For i = 0 To Count - 1
					Pies(i).IsNarrow = Pies(i).Angle < 20 And (Pies(i).PrevPie.Angle < 20 Or Pies(i).NextPie.Angle < 20)
				Next
				For i = 0 To Count - 1
					If Pies(i).IsNarrow Then
						Dim Pie As Pie = Pies(i).PrevPie
						Do Until Pie.IsNarrow
							Pies(i).ExtraAngle -= 10
							Pie = Pie.PrevPie
						Loop
						Pie = Pies(i).NextPie
						Do Until Pie.IsNarrow
							Pies(i).ExtraAngle += 10
							Pie = Pie.NextPie
						Loop
					End If
				Next
				Dim xf = (x2 - x1) / 6
				Dim yf = (y2 - y1) / 3
				Dim Angle1, Angle2 As Single
				Dim Height As Integer = (x2 - x1 - xf * 2) / 10
				Dim Rect As New Rectangle(x1 + xf, y1 + yf - Height, x2 - x1 - 2 * xf, y2 - y1 - 2 * yf)
				Dim Font As New Font(ReportFontRegular, (y2 - y1) / 40)
				Dim Angle As Single
				Dim c As Integer
				Angle = 30
				i = 0
				For i = 0 To Count - 1
					Dim MidAngle = (Angle + Pies(i).Angle / 2) Mod 360
					Dim MidAngle2 = (Angle + (Pies(i).Angle + Pies(i).ExtraAngle) / 2) Mod 360
					Dim TextRec As New Rectangle
					TextRec.Size = G.MeasureString(Titles(i) & "xxx" & vbCrLf & "x", Font).ToSize
					If MidAngle < 180 Then Rect.Offset(0, Height)
					Pies(i).P1.X = Math.Cos(MidAngle / 180 * Math.PI) * Rect.Width / 2 + Rect.Left + Rect.Width / 2
					Pies(i).P1.Y = Math.Sin(MidAngle / 180 * Math.PI) * Rect.Height / 2 + Rect.Top + Rect.Height / 2
					Pies(i).P2.X = Math.Cos(MidAngle2 / 180 * Math.PI) * Rect.Width / 1.2 + Rect.Left + Rect.Width / 2
					Pies(i).P2.Y = Math.Sin(MidAngle2 / 180 * Math.PI) * Rect.Height / 1.2 + Rect.Top + Rect.Height / 2
					G.DrawLine(LinePen, Pies(i).P1, Pies(i).P2)
					TextRec.Location = New Point(Pies(i).P2.X - TextRec.Width / 2, Pies(i).P2.Y - TextRec.Height / 2)
					G.FillRectangle(Brushes.White, TextRec)
					'G.DrawRectangle(LinePen, TextRec)
					Dim SF As New StringFormat
					DrawText(G, Titles(i), Font, Color.Black, TextRec, StrFormat("c", "t"))
					TextRec.Size = G.MeasureString(Pies(i).Percent & "xxx", Font).ToSize
					TextRec.Location = New Point(Pies(i).P2.X - TextRec.Width / 2, Pies(i).P2.Y)
					DrawText(G, Pies(i).Percent, Font, Color.Black, TextRec, Centered)
					If MidAngle < 180 Then Rect.Offset(0, -Height)
					Angle = (Angle + Pies(i).Angle) Mod 360
				Next
				For h As Integer = Height To 0 Step -1
					Angle = 30
					Rect.Offset(0, h)
					c = 0
					For i = 0 To Count - 1
						Dim Tone = 160 + c - Math.Sign(h) * 32
						Dim Brush As New SolidBrush(Color.FromArgb(Tone, Tone, Tone))
						c = (c + 41) Mod 96
						FindRealAngle(Angle, Pies(i).Angle, Rect.Width, Rect.Height, Angle1, Angle2)
						G.FillPie(Brush, Rect, Angle1, Angle2)
						Angle += Pies(i).Angle
					Next
					Rect.Offset(0, -h)
				Next
				Angle = 30
				For i = 0 To Count - 1
					If Angle <= 180 Then
						Dim xc As Single = Math.Cos(Angle / 180 * Math.PI) * Rect.Width / 2 + Rect.Left + Rect.Width / 2
						Dim yc As Single = Math.Sin(Angle / 180 * Math.PI) * Rect.Height / 2 + Rect.Top + Rect.Height / 2
						G.DrawLine(LinePen, xc, yc, xc, yc + Height)
					End If
					Angle = (Angle + Pies(i).Angle) Mod 360
				Next
				Rect.Offset(0, Height)
				G.DrawArc(LinePen, Rect, 0, 180)
				Dim yy1 As Integer = CInt(Rect.Top + Rect.Height / 2)
				Dim yy2 As Integer = CInt(Rect.Top + Rect.Height / 2 - Height)
				G.DrawLine(LinePen, Rect.Left, yy1, Rect.Left, yy2)
				G.DrawLine(LinePen, Rect.Right, yy1, Rect.Right, yy2)
				Rect.Offset(0, -Height)
				Angle = 30
				For i = 0 To Count - 1
					FindRealAngle(Angle, Pies(i).Angle, Rect.Width, Rect.Height, Angle1, Angle2)
					G.DrawPie(LinePen, Rect, Angle1, Angle2)
					Angle += Pies(i).Angle
				Next
		End Select
		G.SmoothingMode = Drawing2D.SmoothingMode.Default

	End Sub

    Private Sub DrawPlane(ByVal G As Graphics, ByVal p1 As PointF, ByVal p2 As PointF, ByVal Depth As Double, Optional ByVal NoShadow As Boolean = False)
        Dim xy(3) As PointF
        Dim c As Byte = If(NoShadow, 240, If(p1.X = p2.X, 192, 224))
        Dim ShadowBrush As New SolidBrush(Color.FromArgb(c, c, c))
        xy(0) = p1
        xy(1) = p2
        xy(2) = New Point(p2.X + Depth, p2.Y - Depth)
        xy(3) = New Point(p1.X + Depth, p1.Y - Depth)
        G.FillPolygon(ShadowBrush, xy)
        G.DrawPolygon(LinePen, xy)
    End Sub

    Private Sub FindRealAngle(ByVal Angle, ByVal SweepingAngle, ByVal x, ByVal y, ByRef RealAngle, ByRef RealSweepingAngle)
        Dim xc As Single = Math.Cos(Angle / 180 * Math.PI) * x
        Dim yc As Single = Math.Sin(Angle / 180 * Math.PI) * y
        RealAngle = Math.Atan2(yc, xc) * 180 / Math.PI
        If RealAngle < 0 Then RealAngle += 360
        xc = Math.Cos((Angle + SweepingAngle) / 180 * Math.PI) * x
        yc = Math.Sin((Angle + SweepingAngle) / 180 * Math.PI) * y
        Dim RealAngle2 = Math.Atan2(yc, xc) * 180 / Math.PI
        If RealAngle2 < 0 Then RealAngle2 += 360
        RealSweepingAngle = RealAngle2 - RealAngle
        If RealSweepingAngle < 0 Then RealSweepingAngle += 360
    End Sub

End Class